Public Class TabStrip
	Inherits PictureBox

	Dim MaxTabWidth As Integer = 180
	Public Tabs As New List(Of Tab)
	Dim TabWidth As Integer = 160

	Event TabSelected()

	Public Function AddTab(ByVal Text As String, ByVal Icon As Image, ByVal Control As Object, Optional ByVal Locked As Boolean = False) As Tab
		Dim Tab As New Tab With {.Locked = Locked, .Control = Control, .Text = Text, .Strip = Me, .Icon = Icon}
		Tabs.Add(Tab)
		Visible = Tabs.Count > 1
		SelectedTab = Tab
		CalculateTabPositions()
		Application.DoEvents()
		Return Tab
	End Function

	Private Sub TabStrip_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseDown
		If Cursor <> Cursors.Hand Then Exit Sub
		If SelectedTab.CloseRect.Contains(e.Location) Then SelectedTab.Close() : Exit Sub
		Dim NewTab As Integer = Int(e.X / TabWidth)
		Cursor = Cursors.Default
		SelectedTab = Tabs(NewTab)
		Refresh()
	End Sub

	Private Sub TabStrip_MouseLeave(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.MouseLeave
		HoverTab = Nothing
		Cursor = Cursors.Default
	End Sub

	Private Sub TabStrip_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseMove
		Dim Index As Integer = Int(e.X / TabWidth)
		If Index < 0 Then Exit Sub
		HoverTab = If(Index >= Tabs.Count, Nothing, Tabs(Index))
		If Not HoverTab Is Nothing Then HoverClose = HoverTab.CloseRect.Contains(e.Location)
		Cursor = If(HoverTab Is SelectedTab, If(HoverTab.CloseRect.Contains(e.Location), Cursors.Hand, Cursors.Default), If(HoverTab Is Nothing, Cursors.Default, Cursors.Hand))
	End Sub

	Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
		If Width <= 0 Or Height <= 0 Then Exit Sub
		Dim G As Graphics = e.Graphics
		G.SmoothingMode = Drawing2D.SmoothingMode.AntiAlias
		G.InterpolationMode = Drawing2D.InterpolationMode.HighQualityBicubic
		G.PixelOffsetMode = Drawing2D.PixelOffsetMode.None
		G.FillRectangle(New SolidBrush(SystemColors.Control), -1, -1, Width + 2, Height + 2)
		G.TextRenderingHint = Drawing.Text.TextRenderingHint.ClearTypeGridFit
		G.DrawLine(New Pen(Color.FromArgb(96, Color.Black)), 0, Height - 2, Width, Height - 2)
		G.DrawLine(New Pen(Color.FromArgb(32, Color.Black)), 0, Height - 3, Width, Height - 3)
		For Each Tab As Tab In Tabs
			Tab.Draw(G, False, False, Height, TabWidth)
		Next
		If Not HoverTab Is Nothing And Not HoverTab Is SelectedTab Then HoverTab.Draw(G, False, True, Height, TabWidth)
		G.DrawLine(Pens.White, 0, Height - 1, Width, Height - 1)
		If Not SelectedTab Is Nothing Then SelectedTab.Draw(G, True, HoverClose, Height, TabWidth)
	End Sub

	Sub CalculateTabPositions()
		If Tabs.Count = 0 Then Exit Sub
		TabWidth = Math.Min((Width - 32) \ Tabs.Count, MaxTabWidth)
		For Each Tab As Tab In Tabs
			Tab.Rect = New Rectangle(Tabs.IndexOf(Tab) * TabWidth - 3, 2, TabWidth + 6, Height)
		Next
		Invalidate()
	End Sub

	Private Sub TabStrip_Resize(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Resize
		CalculateTabPositions()
	End Sub

	Public Sub Switch(Optional ByVal Direction = 1)
		SelectedTab = Tabs((Tabs.IndexOf(SelectedTab) + Direction + Tabs.Count) Mod Tabs.Count)
	End Sub

	Dim m_SelectedTab As Tab
	Property SelectedTab() As Tab
		Get
			Return m_SelectedTab
		End Get
		Set(ByVal Value As Tab)
			If m_SelectedTab Is Value Then Exit Property
			If Not Value Is Nothing AndAlso Not Value.Control Is Nothing Then
				Dim Toolbar As ToolStrip = Value.Control.ToolBar
				Dim c = CType(FindForm(), Object).ToolPanel
				Toolbar.AutoSize = True
				Toolbar.Dock = DockStyle.Fill
				Toolbar.BackColor = Color.Transparent
				Toolbar.Padding = New Padding(6, 6, 6, 5)
				Toolbar.BackColor = Color.Transparent
				Toolbar.Parent = c
				Value.Control.Visible = True
			End If
			If Not m_SelectedTab Is Nothing AndAlso Not m_SelectedTab.Control Is Nothing Then
				m_SelectedTab.Control.Visible = False
				m_SelectedTab.Control.ToolBar.Parent = Nothing
			End If
			m_SelectedTab = Value
			Invalidate()
		End Set
	End Property


	Dim m_HoverTab As Tab
	Property HoverTab() As Tab
		Get
			Return m_HoverTab
		End Get
		Set(ByVal Value As Tab)
			If m_HoverTab Is Value Then Exit Property
			m_HoverTab = Value
			Invalidate()
		End Set
	End Property

	Dim m_HoverClose As Boolean = False
	Property HoverClose() As Boolean
		Get
			Return m_HoverClose
		End Get
		Set(ByVal Value As Boolean)
			If m_HoverClose = Value Then Exit Property
			m_HoverClose = Value
			Invalidate()
		End Set
	End Property

	Public Sub CloseTab()
		FindForm.Controls.Remove(SelectedTab.Control)
		Dim Index As Integer = Tabs.IndexOf(SelectedTab)
		Tabs.Remove(SelectedTab)
		CalculateTabPositions()
		If Index = Tabs.Count Then Index -= 1
		SelectedTab = Tabs(Index)
		SelectedTab.Control.Focus()
		Visible = Tabs.Count > 1
	End Sub

End Class


Public Class Tab
	Public Text As String
	Public Rect As Rectangle
	Public Locked As Boolean
	Public Strip As TabStrip
	Public Icon As Image

	Dim m_Control As Object
	Public Property Control() As Object
		Get
			Return m_Control
		End Get
		Set(ByVal Value As Object)
			m_Control = Value
		End Set
	End Property

	Sub Draw(ByVal G As Graphics, ByVal IsSelected As Boolean, ByVal IsHovered As Boolean, ByVal Height As Integer, ByVal TabWidth As Integer)
		Dim Rect = Me.Rect
		If Rect.Width = 0 Then Exit Sub
		Dim F As StringFormat = New StringFormat	'StrFormat("l", "c")
		F.Trimming = StringTrimming.EllipsisCharacter
		F.FormatFlags = F.FormatFlags Or StringFormatFlags.NoWrap
		Dim Path As New Drawing2D.GraphicsPath(Drawing2D.FillMode.Alternate)
		Path.AddLines(New Point() {New Point(Rect.Left, Rect.Bottom), New Point(Rect.Left + Rect.Height \ 4, Rect.Top), New Point(Rect.Right - Rect.Height \ 4, Rect.Top), New Point(Rect.Right, Rect.Bottom)})
		G.DrawPath(New Pen(Color.FromArgb(96, Color.Black), 2), Path)
		Dim Alpha As Integer = If(IsSelected Or IsHovered, 255, 128)
		G.FillPath(New SolidBrush(Color.FromArgb(Alpha, Color.White)), Path)
		Dim ImageRect As New Rectangle(Rect.Left + 4, Rect.Top, Height - 2, Height - 2)
		Dim TextRec As New Rectangle(Rect.Left + ImageRect.Width, 2, Rect.Width - (ImageRect.Width), Height - 2)
		ImageRect.Inflate(-4, -4)
		If Not Icon Is Nothing Then G.DrawImage(Icon, ImageRect)
		If IsSelected Then TextRec.Width -= Height - 8
		TextRec.Inflate(0, -3)
		If IsSelected Or IsHovered Then
			TextRenderer.DrawText(G, Text, Strip.Font, TextRec, SystemColors.ControlText, Color.Transparent, TextFormatFlags.Left Or TextFormatFlags.VerticalCenter)
		Else
			TextRenderer.DrawText(G, Text, Strip.Font, TextRec, SystemColors.ControlText, Color.Transparent, TextFormatFlags.Left Or TextFormatFlags.VerticalCenter)
		End If
		If IsSelected Then
			Dim R As Rectangle = CloseRect
			If R.Width > 0 Then
				R.Inflate(2, 2)
				R.Width += 1 : R.Height += 1
				FirefoxRenderer.Draw(G, R, IsHovered, False, New Integer() {4, 4, 4, 4})
				R.Width -= 1 : R.Height -= 1
				Dim P2 As New Drawing2D.GraphicsPath(Drawing2D.FillMode.Alternate)
				R.Inflate(-4, -4)
				P2.AddLine(R.Left, R.Top, R.Right, R.Bottom)
				P2.StartFigure()
				P2.AddLine(R.Left, R.Bottom, R.Right, R.Top)
				G.DrawPath(New Pen(Color.FromArgb(128, Color.White), 4), P2)
				G.DrawPath(New Pen(Color.FromArgb(IIf(IsHovered, 255, 192), Color.Red), 2), P2)
			End If
		Else
			G.DrawLine(New Pen(Color.FromArgb(128, Color.Black)), Rect.Left, Height - 2, Rect.Right, Height - 2)
			G.DrawLine(New Pen(Color.FromArgb(64, Color.Black)), Rect.Left, Height - 3, Rect.Right, Height - 3)
			G.DrawLine(New Pen(Color.FromArgb(16, Color.Black)), Rect.Left, Height - 4, Rect.Right, Height - 4)
		End If
		'G.DrawPath(New Pen(Color.FromArgb(IIf(IsSelected, 255, 128), Color.White)), Path)
		If Not IsSelected And Not IsHovered Then G.FillPath(New SolidBrush(Color.FromArgb(64, Color.White)), Path)
	End Sub

	ReadOnly Property CloseRect() As Rectangle
		Get
			If Locked Then Return New Rectangle(0, 0, 0, 0)
			Dim R As New Rectangle(Rect.Right - Rect.Height, Rect.Top + 1, Rect.Height, Rect.Height)
			R.Inflate(-7, -7)
			R.Offset(-2, -3)
			Return R
		End Get
	End Property

	Sub Activate()
		Strip.SelectedTab = Me
	End Sub

	Sub SetText(ByVal Text As String)
		Me.Text = Text
		Strip.Invalidate()
	End Sub

	Sub Close()
		Strip.CloseTab()
	End Sub

End Class

Public Class Button
	Inherits Windows.Forms.Button

	Sub New()
		Me.SetStyle(ControlStyles.AllPaintingInWmPaint, True)
		Me.SetStyle(ControlStyles.OptimizedDoubleBuffer, True)
		Me.SetStyle(ControlStyles.ResizeRedraw, True)
		Me.SetStyle(ControlStyles.SupportsTransparentBackColor, True)
		Me.SetStyle(ControlStyles.UserPaint, True)
		Me.SetStyle(ControlStyles.Opaque, False)
		Me.BackColor = Color.Transparent
	End Sub

	Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
		Dim R = ClientRectangle
		FirefoxRenderer.Draw(e.Graphics, R, Selected Or Focused, Pressed, New Integer() {6, 6, 6, 6})
		R.Height -= 1
		If Image Is Nothing Then
			TextRenderer.DrawText(e.Graphics, Text, Font, R, ForeColor, Color.Transparent, TextFormatFlags.HorizontalCenter + TextFormatFlags.VerticalCenter)
		Else
			R.Offset(22, 0)
			TextRenderer.DrawText(e.Graphics, Text, Font, R, ForeColor, Color.Transparent, TextFormatFlags.Left + TextFormatFlags.VerticalCenter)
			R.Offset(-20, 0)
			R.Width = R.Height
			R.Inflate(-5, -5)
			e.Graphics.InterpolationMode = Drawing2D.InterpolationMode.HighQualityBilinear
			e.Graphics.DrawImage(Image, R)
		End If
	End Sub

	Dim _Selected As Boolean
	Property Selected As Boolean
		Get
			Return _Selected
		End Get
		Set(ByVal Value As Boolean)
			If _Selected = Value Then Exit Property
			_Selected = Value
			Invalidate()
		End Set
	End Property

	Dim _Pressed As Boolean
	Property Pressed As Boolean
		Get
			Return _Pressed
		End Get
		Set(ByVal Value As Boolean)
			If _Pressed = Value Then Exit Property
			_Pressed = Value
			Invalidate()
		End Set
	End Property

	Protected Overrides Sub OnMouseEnter(ByVal e As System.EventArgs)
		MyBase.OnMouseEnter(e)
		Selected = True
	End Sub

	Protected Overrides Sub OnMouseLeave(ByVal e As System.EventArgs)
		MyBase.OnMouseLeave(e)
		Selected = False
	End Sub

	Protected Overrides Sub OnMouseDown(ByVal mevent As System.Windows.Forms.MouseEventArgs)
		MyBase.OnMouseDown(mevent)
		Pressed = True
	End Sub

	Protected Overrides Sub OnMouseUp(ByVal mevent As System.Windows.Forms.MouseEventArgs)
		MyBase.OnMouseUp(mevent)
		Pressed = False
	End Sub

End Class